package _04_queue.my_implements;

import _04_queue.AbstractQueue;

import java.util.ConcurrentModificationException;
import java.util.Iterator;

/**
 * @author: mornd
 * @dateTime: 2023/6/5 - 8:46
 * 环形数组实现1：通过程序控制使数组变成环形，arr[length - 1].next = arr[0]
 * 用 head，tail 判断空满，头指针存储元素，尾指针占1个空位不存储元素
 */
public class ArrayQueue1<E> extends AbstractQueue<E> {

    Object[] data;

    // 头指针
    private int head = 0;
    // 尾指针
    private int tail = 0;

    public ArrayQueue1(int capacity) {
        if (capacity < 0) {
            throw new IllegalArgumentException();
        }
        // +1 是为了多出一个空位只存放尾指针，如果容量为3，则最多只能存储2个元素
        data = new Object[capacity + 1];
    }

    private int getNextPositionIndex() {
        return (tail + 1) % data.length;
    }

    @Override
    public boolean offer(E e) {
        if (isFull()) {
            return false;
        }
        // 插入到尾指针的位置，尾指针向前1步
        data[tail] = e;
        tail = getNextPositionIndex();
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        // 先将头指针元素取出，然后头指针向前1步
        Object e = data[head];
        data[head] = null;
        head = (head + 1) % data.length;
        return (E) e;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return (E) data[head];
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

//    @Override
//    public void clear() {
//        if (!isEmpty()) {
////            for (int i = head; i != tail; i = (i + 1) % data.length) {
////                data[i] = null;
////            }
//            tail = head = 0;
//        }
//    }

    @Override
    public boolean isFull() {
        return (getNextPositionIndex() == head);
    }

    @Override
    public Iterator<E> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        int cursor = head;
        int lastRet = -1;

        @Override
        public boolean hasNext() {
            return cursor != tail;
        }

        @Override
        public E next() {
            Object e = data[lastRet = cursor];
            cursor = (cursor + 1) % data.length;
            return (E) e;
        }

        @Override
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            try {
                ArrayQueue1.this.poll();
                lastRet = -1;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }
}
